'use strict'

// 1.学校管理员

let util = require('util');
let Fiber = require('fibers');
let redis = require('../modules/lib/redis');
let outputLogger = require('../modules/lib/loggers').output;
let DATA_SYNC_DB = 1;
let DATA_SYNC_KEY = 'attendance_data_sync';
let TEST_SYNC_KEY = 'test_data_sync';
let TIMEOUT = 2000;

let models = require('../modules/models');

let User = models.User;
let Role = models.Role;
let School = models.School;
let NatureClass = models.NatureClass;
let Student = models.Student;
let Teacher = models.Teacher;
let Grade = models.Grade;

let UserDao = models.UserDao;
let RoleDao = models.RoleDao;
let SchoolDao = models.SchoolDao;
let NatureClassDao = models.NatureClassDao;
let StudentDao = models.StudentDao;
let TeacherDao = models.TeacherDao;
let GradeDao = models.GradeDao;

let checkTimeSetService = require('../modules/services/checktimeset');

let ROLE_ID_STUDENT = '2244000001000000001';
let ROLE_ID_TEACHER = '2244000001000000002';

function syncData() {
    Fiber(() => {
        let redisClient = redis.getClient();

        redisClient.select(DATA_SYNC_DB);

        if ( process.argv.length == 2 ) {
            while ( true ) {
                let message = redisClient.lpop(DATA_SYNC_KEY);
                if ( !message ) {
                    break;
                }
                redisClient.rpush(TEST_SYNC_KEY, message);
                processMessage(message);
            }

            redisClient.quit();
            setTimeout(syncData, TIMEOUT);
        }
        else if ( process.argv[2] == 'restore' ) {
            while ( true ) {
                let message = redisClient.lpop(TEST_SYNC_KEY);
                if ( !message ) {
                    break;
                }
                redisClient.rpush(DATA_SYNC_KEY, message);
                console.log(message);
            }

            redisClient.quit();
            process.exit();
        }

    }).run();
}

function getRole(roleName) {
    return RoleDao.findOne({
        name: roleName
    });
}

let actions = {
    user: {
        insert(iflyId, data) {
            let user = new User({
                iflyId: iflyId,
                name: data.loginName,
                realName: data.userName,
                status: 1 - Number(data.forbidden),
            });

            UserDao.create(user);
        },
        update(iflyId, data) {
            let user = UserDao.findOne({
                iflyId: iflyId
            });

            if ( !user ) {
                actions.user.insert(iflyId, data); 
                return;
            }

            user.name = data.loginName;
            user.realName = data.userName;
            user.status = 1 - Number(data.forbidden);

            UserDao.update(user);

            let student = StudentDao.findOne({
                user: user.id
            });
            if ( student ) {
                student.name = user.realName;
                StudentDao.update(student);
            }

            let teacher = TeacherDao.findOne({
                user: user.id
            });
            if ( teacher ) {
                teacher.name = teacher.realName;
                TeacherDao.update(teacher);
            }
        },
        delete(iflyId) {
            UserDao.remove({
                iflyId: iflyId
            });
        }
    },
    user_organization: {
        insert(iflyId, data) {
            if ( data.role_id == ROLE_ID_STUDENT ) {
                // 更新用户信息，赋予角色
                let user = UserDao.findOne({
                    iflyId: data.user_id
                });

                if ( !user ) {
                    outputLogger.error(util.format('User %s not found', data.user_id));
                    return;
                }

                user.role = getRole('student');

                UserDao.update(user);

                // 关联学生对象
                let student = StudentDao.findOne({
                    user: user.id
                });

                if ( !student ) {
                    student = new Student({
                        name: user.realName,
                        user: user,
                        attendCount: 0,
                        totalAbsence: 0,
                        lateCount: 0,
                        absenceCount: 0,
                        restCount: 0,
                        earlyCount: 0
                    });

                    StudentDao.create(student);
                }

                // 关联班级
                if ( data.class_id ) {
                    let natureClass = NatureClassDao.findOne({
                        iflyId: data.class_id
                    });

                    if ( !natureClass ) {
                        outputLogger.error(util.format('Nature Class %s not found', data.class_id));
                        return;
                    }

                    NatureClassDao.update({
                        iflyId: data.class_id
                    }, {
                        $push: {
                            students: student.id
                        }
                    });
                }
            }
            //else if ( data.role_id == ROLE_ID_TEACHER ) {
            else {
                // 更新用户信息，赋予角色
                let user = UserDao.findOne({
                    iflyId: data.user_id
                });

                if ( !user ) {
                    outputLogger.error(util.format('User %s not found', data.user_id));
                    return;
                }

                user.role = getRole('teacher');

                UserDao.update(user);

                // 关联教师对象
                let teacher = TeacherDao.findOne({
                    user: user.id
                });

                if ( !teacher ) {
                    teacher = new Teacher({
                        name: user.realName,
                        user: user,
                    });

                    TeacherDao.create(teacher);
                }

                // 关联班级
                if ( data.class_id ) {
                    let natureClass = NatureClassDao.findOne({
                        iflyId: data.class_id
                    });

                    if ( !natureClass ) {
                        outputLogger.error(util.format('Nature Class %s not found', data.class_id));
                        return;
                    }

                    TeacherDao.update({
                        id: teacher.id
                    }, {
                        $push: {
                            managedClasses: natureClass.id
                        }
                    });
                }
                else if ( data.school_id ) {
                    let school = SchoolDao.findOne({
                        iflyId: data.school_id
                    });

                    if ( !school ) {
                        outputLogger.error(util.format('School %s not found', data.school_id));
                        return;
                    }

                    TeacherDao.update({
                        id: teacher.id
                    }, {
                        $set: {
                            managedSchool: school.id
                        }
                    });
                }
            }
        },
        update(iflyId, data) {
            actions.user_organization.insert(iflyId, data);
        },
        delete(iflyId) {
        }
    },
    school: {
        insert(iflyId, data) {
            let school = new School({
                iflyId: iflyId,
                name: data.schoolName,
                checkTimeSet: checkTimeSetService.createInstance()
            });

            SchoolDao.create(school);
        },
        update(iflyId, data) {
            let school = SchoolDao.findOne({
                iflyId: iflyId
            });

            if ( !school ) {
                actions.school.insert(iflyId, data);
                return;
            }

            school.name = data.schoolName;

            SchoolDao.update(school);
        },
        delete(iflyId) {
            SchoolDao.remove({
                iflyId: iflyId
            });
        }
    },
    'class': {
        insert(iflyId, data) {
            console.log(data);

            let natureClass = new NatureClass({
                iflyId: iflyId,
                name: data.className
            });

            NatureClassDao.create(natureClass);

            let gradeName = data.year + '级';
            let grade = GradeDao.findOne({
                iflySchoolId: data.schoolId,
                name: gradeName
            });

            if ( !grade ) {
                grade = new Grade({
                    iflySchoolId: data.schoolId,
                    name: gradeName,
                    natureClasses: [],
                    checkTimeSet: checkTimeSetService.createInstance()
                });

                GradeDao.create(grade);

                let school = SchoolDao.findOne({
                    iflyId: data.schoolId
                });

                if ( !school ) {
                    outputLogger.error(util.format('School %s not found', iflyId));
                    return;
                }

                school.grades.push(grade);
                SchoolDao.update(school);
            }

            grade.natureClasses.push(natureClass);
            GradeDao.update(grade);
        },
        update(iflyId, data) {
            let natureClass = NatureClassDao.findOne({
                iflyId: iflyId
            });

            if ( !natureClass ) {
                actions['class'].insert(iflyId, data);
                return;
            }

            NatureClassDao.update({
                iflyId: iflyId
            }, {
                $set: {
                    name: data.className
                }
            });
        },
        delete(iflyId) {
            NatureClassDao.remove({
                iflyId: iflyId
            });
        }
    }
};

function processMessage(message) {
    message = JSON.parse(message);

    let actionMethod = message.action;
    let actionType = message.code;

    if ( actionType in actions ) {
        console.log(util.format('%s %s', actionMethod, actionType));
        let action = actions[actionType][actionMethod];
        action(message.id, message.data);
    }
}

setTimeout(syncData, TIMEOUT);
